<!DOCTYPE html>

















































<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

  <meta name="description" content="Javadoc API documentation for Dormancy." />

<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.ico" />
<title>

  DormancyAdvisor.Mode


| Dormancy

</title>
<link href="../../../../assets/doclava-developer-docs.css" rel="stylesheet" type="text/css" />
<link href="../../../../assets/customizations.css" rel="stylesheet" type="text/css" />
<script src="../../../../assets/search_autocomplete.js" type="text/javascript"></script>
<script src="../../../../assets/jquery-resizable.min.js" type="text/javascript"></script>
<script src="../../../../assets/doclava-developer-docs.js" type="text/javascript"></script>
<script src="../../../../assets/prettify.js" type="text/javascript"></script>
<script type="text/javascript">
  setToRoot("../../../", "../../../../assets/");
</script>
<script src="../../../../assets/doclava-developer-reference.js" type="text/javascript"></script>
<script src="../../../../assets/navtree_data.js" type="text/javascript"></script>
<script src="../../../../assets/customizations.js" type="text/javascript"></script>
<noscript>
  <style type="text/css">
    html,body{overflow:auto;}
    #body-content{position:relative; top:0;}
    #doc-content{overflow:visible;border-left:3px solid #666;}
    #side-nav{padding:0;}
    #side-nav .toggle-list ul {display:block;}
    #resize-packages-nav{border-bottom:3px solid #666;}
  </style>
</noscript>
</head>

<body class="">

<div id="header">
    <div id="headerLeft">
    
      <span id="masthead-title">Dormancy</span>
    
    </div>
    <div id="headerRight">
      
  <div id="search" >
      <div id="searchForm">
          <form accept-charset="utf-8" class="gsc-search-box" 
                onsubmit="return submit_search()">
            <table class="gsc-search-box" cellpadding="0" cellspacing="0"><tbody>
                <tr>
                  <td class="gsc-input">
                    <input id="search_autocomplete" class="gsc-input" type="text" size="33" autocomplete="off"
                      title="search developer docs" name="q"
                      value="search developer docs"
                      onFocus="search_focus_changed(this, true)"
                      onBlur="search_focus_changed(this, false)"
                      onkeydown="return search_changed(event, true, '../../../')"
                      onkeyup="return search_changed(event, false, '../../../')" />
                  <div id="search_filtered_div" class="no-display">
                      <table id="search_filtered" cellspacing=0>
                      </table>
                  </div>
                  </td>
                  <td class="gsc-search-button">
                    <input type="submit" value="Search" title="search" id="search-button" class="gsc-search-button" />
                  </td>
                  <td class="gsc-clear-button">
                    <div title="clear results" class="gsc-clear-button">&nbsp;</div>
                  </td>
                </tr></tbody>
              </table>
          </form>
      </div><!-- searchForm -->
  </div><!-- search -->
      
    </div>
</div><!-- header -->


  <div class="g-section g-tpl-240" id="body-content">
    <div class="g-unit g-first side-nav-resizable" id="side-nav">
      <div id="swapper">
        <div id="nav-panels">
          <div id="resize-packages-nav">
            <div id="packages-nav">
              <div id="index-links"><nobr>
                <a href="../../../packages.html"  >Package Index</a> | 
                <a href="../../../classes.html" >Class Index</a></nobr>
              </div>
              <ul>
                
    <li class="api apilevel-">
  <a href="../../../at/dormancy/package-summary.html">at.dormancy</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/access/package-summary.html">at.dormancy.access</a></li>
    <li class="selected api apilevel-">
  <a href="../../../at/dormancy/aop/package-summary.html">at.dormancy.aop</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/persistence/package-summary.html">at.dormancy.persistence</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/persister/package-summary.html">at.dormancy.persister</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/persister/callback/package-summary.html">at.dormancy.persister.callback</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/persister/filter/package-summary.html">at.dormancy.persister.filter</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/persister/function/package-summary.html">at.dormancy.persister.function</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/persister/predicate/package-summary.html">at.dormancy.persister.predicate</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/util/package-summary.html">at.dormancy.util</a></li>
              </ul><br/>
            </div> <!-- end packages -->
          </div> <!-- end resize-packages -->
          <div id="classes-nav">
            <ul>
              
              
    <li><h2>Classes</h2>
      <ul>
          <li class="api apilevel-"><a href="../../../at/dormancy/aop/DormancyAdvisor.html">DormancyAdvisor</a></li>
      </ul>
    </li>
              
    <li><h2>Annotations</h2>
      <ul>
          <li class="api apilevel-"><a href="../../../at/dormancy/aop/PersistenceEndpoint.html">PersistenceEndpoint</a></li>
      </ul>
    </li>
              
    <li><h2>Enums</h2>
      <ul>
          <li class="selected api apilevel-"><a href="../../../at/dormancy/aop/DormancyAdvisor.Mode.html">DormancyAdvisor.Mode</a></li>
      </ul>
    </li>
              
              
            </ul><br/>
          </div><!-- end classes -->
        </div><!-- end nav-panels -->
        <div id="nav-tree" style="display:none">
          <div id="index-links"><nobr>
            <a href="../../../packages.html"  >Package Index</a> | 
            <a href="../../../classes.html" >Class Index</a></nobr>
          </div>
        </div><!-- end nav-tree -->
      </div><!-- end swapper -->
    </div> <!-- end side-nav -->
    <script>
      if (!isMobile) {
        $("<a href='#' id='nav-swap' onclick='swapNav();return false;' style='font-size:10px;line-height:9px;margin-left:1em;text-decoration:none;'><span id='tree-link'>Use Tree Navigation</span><span id='panel-link' style='display:none'>Use Panel Navigation</span></a>").appendTo("#side-nav");
        chooseDefaultNav();
        if ($("#nav-tree").is(':visible')) {
          init_default_navtree("../../../");
        } else {
          addLoadEvent(function() {
            scrollIntoView("packages-nav");
            scrollIntoView("classes-nav");
          });
        }
        $("#swapper").css({borderBottom:"2px solid #aaa"});
      } else {
        swapNav(); // tree view should be used on mobile
      }
    </script>



<div class="g-unit" id="doc-content">

<div id="api-info-block">



  
   
  
  
  
  

  
   
  
  
  
  

  
  
  
  

  
   
  
  
  
  


<div class="sum-details-links">

<div>
<a href="DormancyAdvisor.Mode.html">View Documentation</a>
</div>


</div><!-- end sum-details-links -->
<div class="api-level">
  


  
  

</div>
</div><!-- end api-info-block -->


<!-- ======== START OF CLASS DATA ======== -->

<div id="jd-header">
    public
    static 
    final 
    
    enum
<h1>DormancyAdvisor.Mode</h1>



  
  
  

  
    extends <a href="http://download.oracle.com/javase/6/docs/api/index.html?java/lang/Enum.html">Enum</a>&lt;E&nbsp;extends&nbsp;<a href="http://download.oracle.com/javase/6/docs/api/index.html?java/lang/Enum.html">Enum</a>&lt;E&gt;&gt;<br/>
  
  
  

  
  
  


</div><!-- end header -->
<div id="jd-content">
  <pre class="prettyprint">
/*
 * Copyright 2013 Gregor Schauer
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package at.dormancy.aop;

import at.dormancy.Dormancy;
import at.dormancy.persister.EntityPersister;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractPointcutAdvisor;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
import org.springframework.aop.support.annotation.AnnotationMethodMatcher;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.util.Assert;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.Callable;

/**
 * Intercepts calls and performs cloning and merging of Hibernate entities.
 * &lt;p/&gt;
 * At first, an {@link EntityPersister} is resolved in the following sequence:
 * &lt;ol&gt;
 * &lt;li&gt;Use the metadata of the {@link PersistenceEndpoint} annotation on the method to invoke&lt;/li&gt;
 * &lt;li&gt;Use the metadata of the {@link PersistenceEndpoint} annotation on the object instance&lt;/li&gt;
 * &lt;/ol&gt;
 * If any {@link PersistenceEndpoint} annotation is present, get an {@link EntityPersister} from the {@link BeanFactory}
 * with the given {@code name}. Otherwise, get an {@link EntityPersister} of the specified {@code type} from
 * {@link Dormancy}. If no appropriate {@link EntityPersister} is registered, {@link Dormancy} will be used.
 *
 * @author Gregor Schauer
 * @see Dormancy
 * @see EntityPersister
 * @see PersistenceEndpoint
 */
@Aspect
@Order(Ordered.LOWEST_PRECEDENCE) // make sure this is invoked after other aspects e.g., transaction or validation
public class DormancyAdvisor extends AbstractPointcutAdvisor implements MethodInterceptor, BeanFactoryAware {
	protected static final Logger logger = Logger.getLogger(DormancyAdvisor.class);
	protected Class&lt;? extends Annotation&gt; annotationType = PersistenceEndpoint.class;
	protected Pointcut pointcut;
	protected Integer order;

	public enum Mode {
		/**
		 * Processes parameters of intercepted methods only.
		 */
		PARAMETERS,
		/**
		 * Processes results of intercepted methods only.
		 */
		RESULT,
		/**
		 * Processes parameters as well as results of intercepted methods.
		 */
		BOTH
	}

	protected Dormancy dormancy;
	protected Mode mode = Mode.RESULT;
	protected BeanFactory beanFactory;

	@Inject
	public DormancyAdvisor(@Nonnull Dormancy dormancy) {
		this.dormancy = dormancy;
	}

	@Nullable
	@SuppressWarnings("unchecked")
	private Object process(@Nonnull Object[] args, @Nonnull Method method, @Nonnull Object target, @Nonnull Callable&lt;?&gt; callable) throws Throwable {
		// If the method to invoke takes no parameters and does not return anything, directly invoke it
		if (args.length == 0 &amp;&amp; method.getReturnType() == void.class) {
			return callable.call();
		}

		EntityPersister entityPersister = dormancy;

		// Retrieve the persistence endpoint annotation from the method (if present)
		Annotation annotation = method.getAnnotation(annotationType);
		if (annotation == null) {
			// Retrieve the annotation from the object instance (if present)
			annotation = target.getClass().getAnnotation(annotationType);
		}

		// If a persistence endpoint annotation was found
		if (annotation != null &amp;&amp; annotation.annotationType() == PersistenceEndpoint.class) {
			PersistenceEndpoint persistenceEndpoint = PersistenceEndpoint.class.cast(annotation);
			String name = persistenceEndpoint.name();
			if (!StringUtils.isEmpty(name)) {
				// If the name attribute is set, retrieve an EntityPersister from the BeanFactory
				Assert.notNull(beanFactory, "BeanFactory must not be null");
				entityPersister = beanFactory.getBean(name, EntityPersister.class);
			} else if (persistenceEndpoint.types().length &gt; 0) {
				// If types are set, look for an registered EntityPersister
				Class&lt;? extends EntityPersister&gt;[] types = persistenceEndpoint.types();
				for (Class&lt;? extends EntityPersister&gt; clazz : types) {
					entityPersister = dormancy.getEntityPersister(clazz);
					if (entityPersister != null) {
						break;
					}
				}
				if (entityPersister == null) {
					throw new IllegalArgumentException("No EntityPersister registered for any of the types: " + Arrays.toString(types));
				}
			}
		}

		// Process method parameters (if enabled)
		if (mode == Mode.PARAMETERS || mode == Mode.BOTH) {
			if (logger.isDebugEnabled()) {
				logger.debug(String.format("Using %s for method invocation %s.%s(%s)",
						entityPersister.getClass().getSimpleName(), target.getClass().getName(),
						method.getName(), Arrays.toString(args)));
			}
			for (int i = 0; i &lt; args.length; i++) {
				args[i] = entityPersister.merge(args[i]);
			}
		}

		// Invoke the desired method
		Object result = callable.call();

		// Process the result (if enabled)
		if (mode == Mode.RESULT || mode == Mode.BOTH) {
			if (logger.isDebugEnabled()) {
				logger.debug(String.format("Using %s for method result %s.%s(%s) =&gt; %s",
						entityPersister.getClass().getSimpleName(), target.getClass().getName(),
						method.getName(), Arrays.toString(args), result));
			}
			result = result != null ? entityPersister.clone(result) : result;
		}
		return result;
	}

	@Nullable
	public Object around(@Nonnull final ProceedingJoinPoint joinPoint) throws Throwable {
		Method method = MethodSignature.class.cast(joinPoint.getSignature()).getMethod();
		return process(joinPoint.getArgs(), method, joinPoint.getTarget(), new Callable&lt;Object&gt;() {
			@Override
			public Object call() throws Exception {
				try {
					return joinPoint.proceed();
				} catch (Exception e) {
					throw e;
				} catch (Throwable throwable) {
					throw new RuntimeException(throwable);
				}
			}
		});
	}

	@Nullable
	@Override
	public Object invoke(@Nonnull final MethodInvocation invocation) throws Throwable {
		return process(invocation.getArguments(), invocation.getMethod(), invocation.getThis(), new Callable&lt;Object&gt;() {
			@Override
			public Object call() throws Exception {
				try {
					return invocation.proceed();
				} catch (Exception e) {
					throw e;
				} catch (Throwable throwable) {
					throw new RuntimeException(throwable);
				}
			}
		});
	}

	@Nonnull
	@Override
	public Pointcut getPointcut() {
		if (pointcut == null) {
			pointcut = new AnnotationMatchingPointcut(null, annotationType) {
				@Nonnull
				@Override
				public MethodMatcher getMethodMatcher() {
					return new AnnotationMethodMatcher(annotationType) {
						@Override
						public boolean matches(Method method, Class targetClass) {
							return super.matches(method, targetClass)
									|| AopUtils.getTargetClass(targetClass).isAnnotationPresent(annotationType);
						}
					};
				}
			};
		}
		return pointcut;
	}

	@Nonnull
	@Override
	public Advice getAdvice() {
		return this;
	}

	@Override
	public int getOrder() {
		if (order != null) {
			return order;
		}
		Advice advice = getAdvice();
		if (advice instanceof Ordered &amp;&amp; advice != this) {
			return ((Ordered) advice).getOrder();
		}
		return Ordered.LOWEST_PRECEDENCE;
	}

	@Override
	public void setOrder(int order) {
		this.order = order;
	}

	@Override
	public void setBeanFactory(@Nonnull BeanFactory beanFactory) {
		this.beanFactory = beanFactory;
	}

	/**
	 * Sets the Mode that should be used to process method parameters and return values, respectively.
	 *
	 * @param mode the mode to operate
	 */
	public void setMode(@Nonnull Mode mode) {
		this.mode = mode;
	}

	/**
	 * Sets the annotation type that indicates a persistence endpoint.
	 *
	 * @param annotationType the type of the annotation
	 */
	public void setAnnotationType(@Nonnull Class&lt;? extends Annotation&gt; annotationType) {
		this.annotationType = annotationType;
	}
}

  </pre>
</div>
<div id="footer">
Generated by <a href="http://code.google.com/p/doclava/">Doclava</a>.
</div> <!-- end footer -->

</div> <!-- jd-content -->

</div><!-- end doc-content -->

</div> <!-- end body-content --> 

<script type="text/javascript">
init(); /* initialize doclava-developer-docs.js */
</script>

</body>
</html>
